package iscte.iul.dcti.pa.al2011_12.controller;

//import Aluno;
import iscte.iul.dcti.pa.al2011_12.viewer.DynamicTable;

import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import iscte.iul.dcti.pa.al2011_12.model.Cell;
import iscte.iul.dcti.pa.al2011_12.model.Row;
import iscte.iul.dcti.pa.al2011_12.model.Sheet;

import iscte.iul.dcti.pa.al2011_12.utilities.*;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;

public class MyApp implements Observer {

	private Sheet sheet;
	private Cell observableCell = null;
	private DynamicTable dynamicTable;

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		new MyApp().runControl();
	}

	@Override
	public void update(Observable observable, Object object) {
		if (observable instanceof Cell) {
			updateCellsValue((Cell) observable);
		}
	}

	private void runControl() {

		sheet = new Sheet(6, 26);

		Display display = new Display();
		final Shell shell = new Shell(display);
		shell.setLayout(new RowLayout(SWT.HORIZONTAL));

		dynamicTable = new DynamicTable(shell);
		// table.add
		dynamicTable.load(sheet);

		setTableEditor(dynamicTable.getTable());

		shell.pack();
		shell.open();

		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		display.dispose();

		inspectSheet();
	}

	private void setTableEditor(Table table) {
		final TableEditor editor = new TableEditor(table);
		editor.horizontalAlignment = SWT.LEFT;
		editor.grabHorizontal = true;

		addListener(table, editor);

		// TODO por um observador em cada posicao do Viewer???
		// TODO inverter observador e observado??
	}

	/**
	 * 
	 * 
	 * Add listener
	 * 
	 */
	public void addListener(final Table table, final TableEditor editor) {

		table.addListener(SWT.MouseDown, new Listener() { // para o evento MouseDown

					public void handleEvent(Event event) {
						Rectangle clientArea = table.getClientArea();
						Point pt = new Point(event.x, event.y);

						int index = table.getTopIndex();
						while (index < table.getItemCount()) { // para cada linha
							boolean visible = false;
							final TableItem item = table.getItem(index);

							for (int i = 0; i < table.getColumnCount(); i++) { // para cada célula de cada linha

								Rectangle rect = item.getBounds(i);
								if (rect.contains(pt)) {
									final int column = i;
									final Text textBox = new Text(table, SWT.NONE); // para a textbox

									Listener textListener = getListener(item, index, column, textBox);

									textBox.addListener(SWT.FocusOut, textListener);
									textBox.addListener(SWT.Traverse, textListener);

									editor.setEditor(textBox, item, i);
									textBox.setText(item.getText(i));

									textBox.selectAll();
									textBox.setFocus();
									return;
								}
								if (!visible && rect.intersects(clientArea)) {
									visible = true;
								}
							}
							if (!visible)
								return;
							index++;
						}
					}
				});
	}

	private Listener getListener(final TableItem item, final int itemIndex,
			final int columnIndex, final Text textBox) {
		return new Listener() {
			public void handleEvent(final Event e) {

				switch (e.type) {
				case SWT.FocusOut:
					setValue(item, itemIndex, columnIndex, textBox);
					textBox.dispose();
					break;
				case SWT.Traverse:
					switch (e.detail) {
					case SWT.TRAVERSE_RETURN:
						setValue(item, itemIndex, columnIndex, textBox);
						// FALL THROUGH
					case SWT.TRAVERSE_ESCAPE:
						textBox.dispose();
						e.doit = false;
					}
					break;
				}
			}
		};
	}

	private void setValue(final TableItem item, int itemIndex,
			final int columnIndex, final Text textBox) {
		//
		String textValue = textBox.getText();
		Cell targetCell = sheet.getCell(columnIndex, itemIndex);
		if (textValue.charAt(0) == '=') {

			Cell operandCell;
			textValue = textValue.substring(1);
			String[] res = textValue.split("[+]");
			int sum = 0;

			int i = 0;
			for (String string : res) {
				operandCell = sheet
						.getCell(Character.toString(string.charAt(0)),
								Integer.parseInt(Character.toString(string
										.charAt(1))) - 1);
				// cell.ref
				// sum += Integer.parseInt(operandCell.getValue());
				if (i++ > 0) {
					targetCell.addReferrerCell('+', operandCell);
				} else {
					targetCell.addReferrerCell(operandCell);
				}
			}
			textValue = targetCell.doMath();
		}
		// do tipo TableItem
		item.setText(columnIndex, textValue);
		// sheet.setCellValue(Utils.GetColumnIndex(columnIndex), itemIndex,
		// textBox.getText());
		targetCell.setValue(textValue);
	}

	private void updateCellsValue(Cell observableCell) { 
		TableItem tableItem;
		String textValue = "";

		for (Row row : sheet.getRows()) { // para cada linha na folha
			for (Cell cell : row.getCells()) { // para cada celula na linha
				for (Cell referredCell : cell.getReferredCells()) { // para cada celula referida na celula
					if (referredCell == observableCell) {
						tableItem = dynamicTable.getTable().getItem(cell.getOrdinate());
						textValue = cell.doMath();
						tableItem.setText(cell.getAbscissa(), textValue);
					}
				}
			}
		}
	}

	private void inspectSheet() {
		for (Row row : sheet.getRows()) {
			for (Cell cell : row.getCells()) {
				System.out.print(cell.toString() + "");
			}
			System.out.println();
		}
	}
}
